Bullet Collision Detection & Physics Library
btQuantizedBvh.h
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#ifndef BT_QUANTIZED_BVH_H
17#define BT_QUANTIZED_BVH_H
18
19class btSerializer;
20
21//#define DEBUG_CHECK_DEQUANTIZATION 1
22#ifdef DEBUG_CHECK_DEQUANTIZATION
23#ifdef __SPU__
24#define printf spu_printf
25#endif //__SPU__
26
27#include <stdio.h>
28#include <stdlib.h>
29#endif //DEBUG_CHECK_DEQUANTIZATION
30
33
34#ifdef BT_USE_DOUBLE_PRECISION
35#define btQuantizedBvhData btQuantizedBvhDoubleData
36#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
37#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
38#else
39#define btQuantizedBvhData btQuantizedBvhFloatData
40#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
41#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
42#endif
43
44//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
45
46//Note: currently we have 16 bytes per quantized node
47#define MAX_SUBTREE_SIZE_IN_BYTES 2048
48
49// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
50// 4 gives the potential for 16 parts, each with 2^27 triangles (134217728)
51// actually) triangles each (since the sign bit is reserved
52//#define MAX_NUM_PARTS_IN_BITS 10
53#define MAX_NUM_PARTS_IN_BITS 4
54
59{
61
62 //12 bytes
63 unsigned short int m_quantizedAabbMin[3];
64 unsigned short int m_quantizedAabbMax[3];
65 //4 bytes
67
68 bool isLeafNode() const
69 {
70 //skipindex is negative (internal node), triangleindex >=0 (leafnode)
71 return (m_escapeIndexOrTriangleIndex >= 0);
72 }
73 int getEscapeIndex() const
74 {
77 }
78 int getTriangleIndex() const
79 {
81 unsigned int x = 0;
82 unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
83 // Get only the lower bits where the triangle index is stored
84 return (m_escapeIndexOrTriangleIndex & ~(y));
85 }
86 int getPartId() const
87 {
89 // Get only the highest bits where the part index is stored
91 }
92};
93
98{
100
101 //32 bytes
104
105 //4
107
108 //8
109 //for child nodes
112
113 //pad the size to 64 bytes
114 char m_padding[20];
115};
116
120{
121public:
123
124 //12 bytes
125 unsigned short int m_quantizedAabbMin[3];
126 unsigned short int m_quantizedAabbMax[3];
127 //4 bytes, points to the root of the subtree
129 //4 bytes
131 int m_padding[3];
132
134 {
135 //memset(&m_padding[0], 0, sizeof(m_padding));
136 }
137
139 {
140 m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
141 m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
142 m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
143 m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
144 m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
145 m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
146 }
147};
148
150{
151public:
153
154 virtual void processNode(int subPart, int triangleIndex) = 0;
155};
156
159
164
170{
171public:
178
179protected:
183
184 int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
185
187 //quantization data
189
194
197
198 //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
200
203 void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
204 {
206 {
207 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
208 }
209 else
210 {
211 m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
212 }
213 }
214 void setInternalNodeAabbMax(int nodeIndex, const btVector3& aabbMax)
215 {
217 {
218 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
219 }
220 else
221 {
222 m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
223 }
224 }
225
226 btVector3 getAabbMin(int nodeIndex) const
227 {
229 {
230 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
231 }
232 //non-quantized
233 return m_leafNodes[nodeIndex].m_aabbMinOrg;
234 }
235 btVector3 getAabbMax(int nodeIndex) const
236 {
238 {
239 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
240 }
241 //non-quantized
242 return m_leafNodes[nodeIndex].m_aabbMaxOrg;
243 }
244
245 void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
246 {
248 {
249 m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
250 }
251 else
252 {
253 m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
254 }
255 }
256
257 void mergeInternalNodeAabb(int nodeIndex, const btVector3& newAabbMin, const btVector3& newAabbMax)
258 {
260 {
261 unsigned short int quantizedAabbMin[3];
262 unsigned short int quantizedAabbMax[3];
263 quantize(quantizedAabbMin, newAabbMin, 0);
264 quantize(quantizedAabbMax, newAabbMax, 1);
265 for (int i = 0; i < 3; i++)
266 {
267 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
268 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
269
270 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
271 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
272 }
273 }
274 else
275 {
276 //non-quantized
277 m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
278 m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
279 }
280 }
281
282 void swapLeafNodes(int firstIndex, int secondIndex);
283
284 void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
285
286protected:
287 void buildTree(int startIndex, int endIndex);
288
289 int calcSplittingAxis(int startIndex, int endIndex);
290
291 int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
292
293 void walkStacklessTree(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
294
295 void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
296 void walkStacklessQuantizedTree(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
297 void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
298
300 void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
301
303 void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
304
307
308 void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
309
310public:
312
314
315 virtual ~btQuantizedBvh();
316
318 void setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin = btScalar(1.0));
321 void buildInternal();
323
324 void reportAabbOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
325 void reportRayOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
326 void reportBoxCastOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const;
327
328 SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point, int isMax) const
329 {
331
332 btAssert(point.getX() <= m_bvhAabbMax.getX());
333 btAssert(point.getY() <= m_bvhAabbMax.getY());
334 btAssert(point.getZ() <= m_bvhAabbMax.getZ());
335
336 btAssert(point.getX() >= m_bvhAabbMin.getX());
337 btAssert(point.getY() >= m_bvhAabbMin.getY());
338 btAssert(point.getZ() >= m_bvhAabbMin.getZ());
339
344 if (isMax)
345 {
346 out[0] = (unsigned short)(((unsigned short)(v.getX() + btScalar(1.)) | 1));
347 out[1] = (unsigned short)(((unsigned short)(v.getY() + btScalar(1.)) | 1));
348 out[2] = (unsigned short)(((unsigned short)(v.getZ() + btScalar(1.)) | 1));
349 }
350 else
351 {
352 out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
353 out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
354 out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
355 }
356
357#ifdef DEBUG_CHECK_DEQUANTIZATION
358 btVector3 newPoint = unQuantize(out);
359 if (isMax)
360 {
361 if (newPoint.getX() < point.getX())
362 {
363 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
364 }
365 if (newPoint.getY() < point.getY())
366 {
367 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
368 }
369 if (newPoint.getZ() < point.getZ())
370 {
371 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
372 }
373 }
374 else
375 {
376 if (newPoint.getX() > point.getX())
377 {
378 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
379 }
380 if (newPoint.getY() > point.getY())
381 {
382 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
383 }
384 if (newPoint.getZ() > point.getZ())
385 {
386 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
387 }
388 }
389#endif //DEBUG_CHECK_DEQUANTIZATION
390 }
391
392 SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2, int isMax) const
393 {
395
396 btVector3 clampedPoint(point2);
397 clampedPoint.setMax(m_bvhAabbMin);
398 clampedPoint.setMin(m_bvhAabbMax);
399
400 quantize(out, clampedPoint, isMax);
401 }
402
403 SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
404 {
405 btVector3 vecOut;
406 vecOut.setValue(
407 (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
408 (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
409 (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
410 vecOut += m_bvhAabbMin;
411 return vecOut;
412 }
413
416 {
417 m_traversalMode = traversalMode;
418 }
419
424
429
431
433 unsigned calculateSerializeBufferSize() const;
434
436 virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
437
439 static btQuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
440
441 static unsigned int getAlignmentSerializationPadding();
443
444 virtual int calculateSerializeBufferSizeNew() const;
445
447 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
448
449 virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
450
451 virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
452
454
456 {
457 return m_useQuantization;
458 }
459
460private:
461 // Special "copy" constructor that allows for in-place deserialization
462 // Prevents btVector3's default constructor from being called, but doesn't inialize much else
463 // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
464 btQuantizedBvh(btQuantizedBvh & other, bool ownsMemory);
465};
466
467// clang-format off
468// parser needs * with the name
470{
473 unsigned short m_quantizedAabbMin[3];
474 unsigned short m_quantizedAabbMax[3];
475};
476
486
496
497
504
521
538// clang-format on
539
544
545#endif //BT_QUANTIZED_BVH_H
btAlignedObjectArray< btOptimizedBvhNode > NodeArray
for code readability:
btAlignedObjectArray< btBvhSubtreeInfo > BvhSubtreeInfoArray
#define MAX_NUM_PARTS_IN_BITS
btAlignedObjectArray< btQuantizedBvhNode > QuantizedNodeArray
#define btQuantizedBvhData
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition btScalar.h:314
#define ATTRIBUTE_ALIGNED16(a)
Definition btScalar.h:99
#define SIMD_FORCE_INLINE
Definition btScalar.h:98
#define btAssert(x)
Definition btScalar.h:153
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
unsigned short int m_quantizedAabbMax[3]
unsigned short int m_quantizedAabbMin[3]
void setAabbFromQuantizeNode(const btQuantizedBvhNode &quantizedNode)
virtual void processNode(int subPart, int triangleIndex)=0
The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
void setInternalNodeAabbMax(int nodeIndex, const btVector3 &aabbMax)
NodeArray m_leafNodes
void setQuantizationValues(const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax, btScalar quantizationMargin=btScalar(1.0))
***************************************** expert/internal use only *************************
QuantizedNodeArray & getLeafNodeArray()
btVector3 m_bvhAabbMax
void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
QuantizedNodeArray m_quantizedLeafNodes
btTraversalMode m_traversalMode
void quantize(unsigned short *out, const btVector3 &point, int isMax) const
BvhSubtreeInfoArray & getSubtreeInfoArray()
btVector3 m_bvhQuantization
btVector3 m_bvhAabbMin
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
@ TRAVERSAL_STACKLESS_CACHE_FRIENDLY
BvhSubtreeInfoArray m_SubtreeHeaders
NodeArray m_contiguousNodes
QuantizedNodeArray & getQuantizedNodeArray()
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode *treeNodeA, const btQuantizedBvhNode *treeNodeB, btNodeOverlapCallback *nodeCallback) const
use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void setInternalNodeAabbMin(int nodeIndex, const btVector3 &aabbMin)
two versions, one for quantized and normal nodes.
void mergeInternalNodeAabb(int nodeIndex, const btVector3 &newAabbMin, const btVector3 &newAabbMax)
BT_DECLARE_ALIGNED_ALLOCATOR()
virtual int calculateSerializeBufferSizeNew() const
void quantizeWithClamp(unsigned short *out, const btVector3 &point2, int isMax) const
void setTraversalMode(btTraversalMode traversalMode)
setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree trave...
btVector3 getAabbMax(int nodeIndex) const
btVector3 getAabbMin(int nodeIndex) const
QuantizedNodeArray m_quantizedContiguousNodes
btVector3 unQuantize(const unsigned short *vecIn) const
btVector3 can be used to represent 3D points and vectors.
Definition btVector3.h:82
const btScalar & getZ() const
Return the z value.
Definition btVector3.h:565
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition btVector3.h:609
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition btVector3.h:640
const btScalar & getY() const
Return the y value.
Definition btVector3.h:563
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition btVector3.h:626
const btScalar & getX() const
Return the x value.
Definition btVector3.h:561
unsigned short m_quantizedAabbMin[3]
unsigned short m_quantizedAabbMax[3]
btVector3DoubleData m_aabbMaxOrg
btVector3DoubleData m_aabbMinOrg
btVector3FloatData m_aabbMaxOrg
btVector3FloatData m_aabbMinOrg
btOptimizedBvhNode contains both internal and leaf node information.
btBvhSubtreeInfoData * m_subTreeInfoPtr
btVector3DoubleData m_bvhAabbMin
btVector3DoubleData m_bvhAabbMax
btVector3DoubleData m_bvhQuantization
btQuantizedBvhNodeData * m_quantizedContiguousNodesPtr
btOptimizedBvhNodeDoubleData * m_contiguousNodesPtr
btOptimizedBvhNodeFloatData * m_contiguousNodesPtr
btVector3FloatData m_bvhAabbMin
btBvhSubtreeInfoData * m_subTreeInfoPtr
btVector3FloatData m_bvhQuantization
btQuantizedBvhNodeData * m_quantizedContiguousNodesPtr
btVector3FloatData m_bvhAabbMax
unsigned short m_quantizedAabbMax[3]
unsigned short m_quantizedAabbMin[3]
btQuantizedBvhNode is a compressed aabb node, 16 bytes.
unsigned short int m_quantizedAabbMin[3]
int getPartId() const
unsigned short int m_quantizedAabbMax[3]
bool isLeafNode() const
int getEscapeIndex() const
int getTriangleIndex() const